package com.isoft.c2team3service2.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.List;

@Component
public class JwtUtil {

    // JWT 密钥（建议在 application.yml 中配置，避免硬编码）
    @Value("${jwt.secret:your-default-secret-key-32bit-length!}") // 至少32位
    private String secret;

    // JWT 过期时间（单位：毫秒，这里配置2小时）
    @Value("${jwt.expiration:7200000}")
    private Long expiration;

    // 生成密钥（避免密钥长度不足导致的异常）
    private SecretKey getSecretKey() {
        return Keys.hmacShaKeyFor(secret.getBytes());
    }

    public Long getExpiration() {
        return expiration;
    }

    /**
     * 生成 JWT Token
     * @param userId 用户ID
     * @param email 用户邮箱（作为用户名）
     * @param roles 用户角色列表（如["艺人"]）
     * @return JWT Token
     */
    public String generateToken(Integer userId, String email,List<String> roles) {
        Date now = new Date();
        Date expDate = new Date(now.getTime() + expiration);

        return Jwts.builder()
                .setSubject(email) // 设置主题（通常存用户名/邮箱）
                .claim("userId", userId) // 自定义Claim：用户ID
                .claim("roles", roles) // 自定义Claim：用户角色
                .setIssuedAt(now) // 签发时间
                .setExpiration(expDate) // 过期时间
                .signWith(getSecretKey(), SignatureAlgorithm.HS256) // 签名算法
                .compact();
    }

    /**
     * 解析 JWT Token，获取所有Claim
     * @param token JWT Token（不含 Bearer 前缀）
     * @return Claims 对象
     */
    public Claims parseToken(String token) {
        // 移除Token中所有空白字符（解决Compact JWT strings may not contain whitespace错误）
        String cleanToken = token.replaceAll("\\s+", "");

        return Jwts.parser()
                .setSigningKey(getSecretKey()) // 验签密钥
                .build()
                .parseClaimsJws(cleanToken) // 解析清理后的Token
                .getBody(); // 获取Claim
    }

    /**
     * 验证 Token 是否过期
     * @param claims 解析后的Claim
     * @return true=已过期，false=未过期
     */
    public boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }
}
